package com.ssy.lingxi.member.merchant.serviceimpl.web;

import com.querydsl.core.types.Projections;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import com.ssy.lingxi.common.constant.basic.EnableDisableStatus;
import com.ssy.lingxi.common.constant.basic.UserLoginSourceEnum;
import com.ssy.lingxi.common.constant.member.MemberLevelTypeEnum;
import com.ssy.lingxi.common.constant.member.MemberTypeEnum;
import com.ssy.lingxi.common.constant.member.RoleTypeEnum;
import com.ssy.lingxi.common.exception.BusinessException;
import com.ssy.lingxi.common.model.dto.UserLoginCacheDTO;
import com.ssy.lingxi.common.model.vo.PageVO;
import com.ssy.lingxi.common.response.PageData;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.common.utils.CollectionPageUtil;
import com.ssy.lingxi.common.utils.DateTimeUtil;
import com.ssy.lingxi.member.merchant.api.constant.MemberLevelRuleTypeEnum;
import com.ssy.lingxi.member.merchant.api.constant.MemberRelationTypeEnum;
import com.ssy.lingxi.member.merchant.api.constant.MemberRightTypeEnum;
import com.ssy.lingxi.member.merchant.entity.*;
import com.ssy.lingxi.member.merchant.model.vo.basic.response.RoleQueryVO;
import com.ssy.lingxi.member.merchant.model.vo.lrc.request.*;
import com.ssy.lingxi.member.merchant.model.vo.lrc.response.*;
import com.ssy.lingxi.member.merchant.repository.*;
import com.ssy.lingxi.member.merchant.service.base.IBaseMemberCacheService;
import com.ssy.lingxi.member.merchant.service.base.IBaseSiteService;
import com.ssy.lingxi.member.merchant.service.web.IMemberLevelConfigService;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.persistence.criteria.Predicate;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 会员等级配置服务接口实现类
 * @author 万宁
 * @version 2.0.0
 * @date 2020-09-21
 */
@Service
public class MemberLevelConfigServiceImpl implements IMemberLevelConfigService {
    @Resource
    private IBaseMemberCacheService memberCacheService;

    @Resource
    private MemberRelationRepository relationRepository;

    @Resource
    private RoleRepository roleRepository;

    @Resource
    private MemberLevelRuleConfigRepository memberLevelRuleConfigRepository;

    @Resource
    private MemberLevelConfigRepository memberLevelConfigRepository;

    @Resource
    private BaseRightConfigRepository baseRightConfigRepository;

    @Resource
    private MemberRightConfigRepository memberRightConfigRepository;

    @Resource
    private RoleRuleRepository roleRuleRepository;

    @Resource
    private MemberLevelRightRepository memberLevelRightRepository;

    @Resource
    private IBaseSiteService baseSiteService;

    @Resource
    private JPAQueryFactory jpaQueryFactory;

    /**
     * 分页查询会员升级规则
     *
     * @param headers HttpHeaders信息
     * @param pageVO  接口参数
     * @return 操作结果
     */
    @Override
    public Wrapper<PageData<MemberLevelRuleConfigQueryVO>> pageMemberLevelRuleConfig(HttpHeaders headers, PageVO pageVO) {
        UserLoginCacheDTO loginUser = memberCacheService.checkUserFromCache(headers);

        Pageable page = PageRequest.of(pageVO.getCurrent() - 1, pageVO.getPageSize(), Sort.by("id").ascending());
        Page<MemberLevelRuleConfigDO> result = memberLevelRuleConfigRepository.findByMemberIdAndRoleId(loginUser.getMemberId(), loginUser.getMemberRoleId(), page);

        return Wrapper.success(new PageData<>(result.getTotalElements(), result.getContent().stream().map(c -> {
            MemberLevelRuleConfigQueryVO configVO = new MemberLevelRuleConfigQueryVO();
            configVO.setId(c.getId());
            configVO.setRuleName(c.getRule().getRuleName());
            configVO.setRuleTypeEnum(c.getRule().getRuleTypeEnum());
            if (c.getRule().getRuleTypeEnum().equals(MemberLevelRuleTypeEnum.BY_TRADE.getCode())) {
                //交易规则按小数保存，前端页面按百分比显示，所以要乘以100返回给前端
                configVO.setScore(c.getScore().multiply(new BigDecimal(100)).intValue());
            } else {
                configVO.setScore(c.getScore().intValue());
            }
            configVO.setLevelTypeName(c.getRule().getMemberLevelTypeName());
            configVO.setRemark(c.getRule().getRemark());
            return configVO;
        }).collect(Collectors.toList())));
    }

    /**
     * 修改会员升级规则可获取的分值
     *
     * @param headers HttpHeaders信息
     * @param ruleVO  接口参数
     * @return 操作结果
     */
    @Override
    public Wrapper<Void> updateMemberLevelRuleConfigScore(HttpHeaders headers, MemberLevelRuleConfigUpdateScoreVO ruleVO) {
        UserLoginCacheDTO loginUser = memberCacheService.checkUserFromCache(headers);

        List<MemberLevelRuleConfigDO> configDOList = memberLevelRuleConfigRepository.findByMemberIdAndRoleId(loginUser.getMemberId(), loginUser.getMemberRoleId());
        List<MemberLevelRuleConfigDO> saveList = new ArrayList<>();
        for (MemberLevelRuleConfigUpdateScoreVO.ScoreItem item : ruleVO.getItems()) {
            if (item.getId() == null || item.getId() <= 0) {
                return Wrapper.fail(ResponseCode.REQUEST_PARAM_CHECK_FAILED);
            }

            MemberLevelRuleConfigDO configDO = configDOList.stream().filter(c -> c.getId().equals(item.getId())).findFirst().orElse(null);
            if (configDO == null) {
                return Wrapper.fail(ResponseCode.MC_MS_MEMBER_LEVEL_RULE_DOES_NOT_EXIST);
            }

            if (item.getScore() == null || item.getScore().compareTo(new BigDecimal(0)) < 0) {
                return Wrapper.fail(ResponseCode.MC_MS_MEMBER_LEVEL_RULE_PARAMETER_MUST_BE_POSITIVE_OR_ZERO);
            }

            if (configDO.getRule().getRuleTypeEnum().equals(MemberLevelRuleTypeEnum.BY_TRADE.getCode())) {
                if (item.getScore().compareTo(new BigDecimal(100)) > 0) {
                    return Wrapper.fail(ResponseCode.MC_MS_MEMBER_TRADE_LEVEL_RULE_MUST_LESSTHAN_OR_EQUAL_100);
                }
                configDO.setScore(item.getScore().divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP));
            } else {
                configDO.setScore(item.getScore());
            }

            saveList.add(configDO);
        }

        if (!CollectionUtils.isEmpty(saveList)) {
            memberLevelRuleConfigRepository.saveAll(saveList);
        }

        return Wrapper.success();
    }

    /**
     * 分页查询会员等级配置
     *
     * @param headers Http头部信息
     * @param pageVO  接口参数
     * @return 查询结果
     */
    @Transactional(rollbackFor = BusinessException.class)
    @Override
    public Wrapper<PageData<MemberLevelQueryVO>> pageMemberLevels(HttpHeaders headers, MemberLevelPageVO pageVO) {
        UserLoginCacheDTO loginUser = memberCacheService.checkUserFromCache(headers);

        QMemberLevelConfigDO qMemberLevelConfig = QMemberLevelConfigDO.memberLevelConfigDO;
        QRoleDO qRole = QRoleDO.roleDO;

        JPAQuery<MemberLevelQueryVO> query = jpaQueryFactory.select(Projections.constructor(MemberLevelQueryVO.class, qMemberLevelConfig.id, qMemberLevelConfig.level, qMemberLevelConfig.levelTag, qMemberLevelConfig.levelType, qMemberLevelConfig.scoreTag, qMemberLevelConfig.roleId, qRole.roleName, qRole.roleType.typeEnum, qRole.memberType.typeEnum, qMemberLevelConfig.point, qMemberLevelConfig.status))
                .from(qMemberLevelConfig)
                .leftJoin(qRole).on(qMemberLevelConfig.subRoleId.eq(qRole.id))
                .where(qMemberLevelConfig.memberId.eq(loginUser.getMemberId()).and(qMemberLevelConfig.roleId.eq(loginUser.getMemberRoleId())))
                .orderBy(qMemberLevelConfig.id.desc())
                .limit(pageVO.getPageSize()).offset(pageVO.getCurrentOffset());

        if(StringUtils.hasText(pageVO.getLevelTag())) {
            query.where(qMemberLevelConfig.levelTag.like("%" + pageVO.getLevelTag().trim() + "%"));
        }

        if(StringUtils.hasText(pageVO.getRoleName())) {
            query.where(qRole.roleName.like("%" + pageVO.getRoleName().trim() + "%"));
        }

        return Wrapper.success(new PageData<>(query.fetchCount(), query.fetch()));
    }

    @Override
    public Wrapper<PageData<MemberLevelQueryVO>> pageMemberLevelByConsumer(HttpHeaders headers, MemberLevelPageVO pageVO) {
        UserLoginCacheDTO loginUser = memberCacheService.checkUserFromCache(headers);
        QMemberLevelConfigDO qMemberLevelConfig = QMemberLevelConfigDO.memberLevelConfigDO;
        QRoleDO qRole = QRoleDO.roleDO;

        JPAQuery<MemberLevelQueryVO> query = jpaQueryFactory.select(Projections.constructor(MemberLevelQueryVO.class, qMemberLevelConfig.id, qMemberLevelConfig.level, qMemberLevelConfig.levelTag, qMemberLevelConfig.levelType, qMemberLevelConfig.scoreTag, qMemberLevelConfig.subRoleId, qRole.roleName, qRole.roleType.typeEnum, qRole.memberType.typeEnum, qMemberLevelConfig.point, qMemberLevelConfig.status))
                .from(qMemberLevelConfig)
                .leftJoin(qRole).on(qMemberLevelConfig.subRoleId.eq(qRole.id))
                .where(qMemberLevelConfig.memberId.eq(loginUser.getMemberId()).and(qMemberLevelConfig.roleId.eq(loginUser.getMemberRoleId())))
                .where(qRole.roleType.typeEnum.eq(RoleTypeEnum.SERVICE_CONSUMER.getCode()))
                .where(qRole.memberType.typeEnum.eq(MemberTypeEnum.MERCHANT.getCode()).or(qRole.memberType.typeEnum.eq(MemberTypeEnum.MERCHANT_PERSONAL.getCode())))
                .orderBy(qMemberLevelConfig.id.desc())
                .limit(pageVO.getPageSize()).offset(pageVO.getCurrentOffset());

        if(StringUtils.hasText(pageVO.getLevelTag())) {
            query.where(qMemberLevelConfig.levelTag.like("%" + pageVO.getLevelTag().trim() + "%"));
        }

        if(StringUtils.hasText(pageVO.getRoleName())) {
            query.where(qRole.roleName.like("%" + pageVO.getRoleName().trim() + "%"));
        }

        return Wrapper.success(new PageData<>(query.fetchCount(), query.fetch()));
    }

    /**
     * 新增或修改会员等级时，查询等级类型列表
     *
     * @param headers Http头部信息
     * @return 查询结果
     */
    @Override
    public Wrapper<List<MemberLevelTypeVO>> findMemberLevelTypes(HttpHeaders headers) {
        UserLoginCacheDTO loginUser = memberCacheService.checkUserFromCache(headers);
        List<MemberLevelTypeEnum> levelTypeEnums = loginUser.getLoginSource().equals(UserLoginSourceEnum.BUSINESS_MANAGEMENT_PLATFORM.getCode()) ? Stream.of(MemberLevelTypeEnum.PLATFORM).collect(Collectors.toList()) : (loginUser.getMemberLevelType().equals(MemberLevelTypeEnum.MERCHANT.getCode()) ? Stream.of(MemberLevelTypeEnum.MERCHANT).collect(Collectors.toList()) : Stream.of(MemberLevelTypeEnum.CHANNEL).collect(Collectors.toList()));
        return Wrapper.success(levelTypeEnums.stream().map(levelType -> new MemberLevelTypeVO(levelType.getCode(), levelType.getMessage())).sorted(Comparator.comparingInt(MemberLevelTypeVO::getLevelType)).collect(Collectors.toList()));
    }

    /**
     * 新增或修改会员等级时，分页查询会员角色列表
     *
     * @param headers Http头部信息
     * @param pageVO  接口参数
     * @return 查询结果
     */
    @Transactional(rollbackFor = BusinessException.class)
    @Override
    public Wrapper<PageData<RoleQueryVO>> pageRoles(HttpHeaders headers, PageVO pageVO) {
        UserLoginCacheDTO loginUser = memberCacheService.checkUserFromCache(headers);

        QRoleDO qRole = QRoleDO.roleDO;

        long totalCount = 0L;
        List<RoleQueryVO> result = new ArrayList<>();

        if(loginUser.getLoginSource().equals(UserLoginSourceEnum.BUSINESS_MANAGEMENT_PLATFORM.getCode())) {
            JPAQuery<RoleQueryVO> query = jpaQueryFactory.select(Projections.constructor(RoleQueryVO.class, qRole.id, qRole.roleName, qRole.roleType.typeEnum, qRole.memberType.typeEnum))
                    .from(qRole)
                    .where(qRole.relType.ne(MemberRelationTypeEnum.PLATFORM.getCode()))
                    .orderBy(qRole.id.asc())
                    .limit(pageVO.getPageSize()).offset(pageVO.getCurrentOffset());
            totalCount = query.fetchCount();
            result = query.fetch();
        } else {
            //1、如果【PAAS-站点管理】未勾选【SAAS多租户部署】且当前会员类型是企业会员或个人会员则会员角色数据从PAAS【会员角色权限设置--会员角色设置】中取会员类型为企业会员或个人会员且状态为有效的会员角色、角色类型，会员类型数据
            //2、如果【PAAS-站点管理】未勾选【SAAS多租户部署】且当前会员类型是渠道企业会员或渠道个人会员则会员角色数据从PAAS【会员角色权限设置--会员角色设置】中取会员类型为渠道企业会员或渠道个人会员且状态为有效的会员角色、角色类型，会员类型数据
            //3、如果【PAAS-站点管理】有勾选【SAAS多租户部署】，则会员角色数据从【平台后台--系统管理--平台规则--会员角色规则配置】中取【下属会员适用会员角色】的会员角色数据
            Wrapper<Boolean> tenantResult = baseSiteService.isEnableMultiTenancy(headers);
            if(tenantResult.getCode() != ResponseCode.SUCCESS.getCode()) {
                return Wrapper.fail(tenantResult.getCode(), tenantResult.getMessage());
            }

            if(tenantResult.getData()) {
                MemberRoleRuleDO roleRule = roleRuleRepository.findByMemberId(loginUser.getMemberId());
                if(roleRule != null && !CollectionUtils.isEmpty(roleRule.getSubMemberRoleRule())) {
                    totalCount = roleRule.getSubMemberRoleRule().size();
                    result = CollectionPageUtil.pageList(roleRule.getSubMemberRoleRule().stream().sorted(Comparator.comparingLong(RoleDO::getId)).collect(Collectors.toList()), pageVO.getCurrent(), pageVO.getPageSize()).stream().map(role -> new RoleQueryVO(role.getId(), role.getRoleName(), role.getRoleType().getTypeEnum(), role.getMemberType().getTypeEnum())).collect(Collectors.toList());
                }
            } else {
                JPAQuery<RoleQueryVO> query = jpaQueryFactory.select(Projections.constructor(RoleQueryVO.class, qRole.id, qRole.roleName, qRole.roleType.typeEnum, qRole.memberType.typeEnum))
                        .from(qRole)
                        .where(qRole.relType.ne(MemberRelationTypeEnum.PLATFORM.getCode()))
                        .orderBy(qRole.id.asc())
                        .limit(pageVO.getPageSize()).offset(pageVO.getCurrentOffset());

                if(loginUser.getMemberLevelType().equals(MemberLevelTypeEnum.MERCHANT.getCode())) {
                    query.where(qRole.memberType.typeEnum.eq(MemberTypeEnum.MERCHANT.getCode()).or(qRole.memberType.typeEnum.eq(MemberTypeEnum.MERCHANT_PERSONAL.getCode())));
                }

                if(loginUser.getMemberLevelType().equals(MemberLevelTypeEnum.CHANNEL.getCode())) {
                    query.where(qRole.memberType.typeEnum.eq(MemberTypeEnum.CHANNEL.getCode()).or(qRole.memberType.typeEnum.eq(MemberTypeEnum.CHANNEL_PERSONAL.getCode())));
                }

                totalCount = query.fetchCount();
                result = query.fetch();
            }
        }

        return Wrapper.success(new PageData<>(totalCount, result));
    }

    /**
     * 新增或修改会员等级
     *
     * @param headers Http头部信息
     * @param levelVO 接口参数
     * @return 操作结果
     */
    @Transactional(rollbackFor = BusinessException.class)
    @Override
    public Wrapper<Void> createMemberLevel(HttpHeaders headers, MemberLevelVO levelVO) {
        UserLoginCacheDTO loginUser = memberCacheService.checkUserFromCache(headers);

        //如果角色Id列表为空，返回
        if(CollectionUtils.isEmpty(levelVO.getRoleIds())) {
            return Wrapper.success();
        }

        //判断角色是否存在
        List<RoleDO> roles = roleRepository.findAllById(levelVO.getRoleIds());
        if(roles.size() != levelVO.getRoleIds().size()) {
            return Wrapper.fail(ResponseCode.MC_MS_ROLE_DOES_NOT_EXIST);
        }

        //根据等级、下级会员角色Id 判断是否已经存在
        if(memberLevelConfigRepository.existsByMemberIdAndRoleIdAndLevelAndSubRoleIdIn(loginUser.getMemberId(), loginUser.getMemberRoleId(), levelVO.getLevel(), levelVO.getRoleIds())) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_LEVEL_CONFIG_EXISTS);
        }

        List<MemberLevelConfigDO> levelConfigs = levelVO.getRoleIds().stream().map(roleId -> {
            MemberLevelConfigDO levelConfig = new MemberLevelConfigDO();
            levelConfig.setMemberId(loginUser.getMemberId());
            levelConfig.setRoleId(loginUser.getMemberRoleId());
            levelConfig.setSubRoleId(roleId);
            levelConfig.setLevel(levelVO.getLevel());
            levelConfig.setLevelTag(levelVO.getLevelTag());
            levelConfig.setScoreTag(levelVO.getScoreTag());
            levelConfig.setPoint(0);
            levelConfig.setStatus(EnableDisableStatus.ENABLE.getCode());
            levelConfig.setRights(new HashSet<>());
            levelConfig.setLevelType(levelVO.getLevelType());
            levelConfig.setRemark(StringUtils.hasText(levelVO.getRemark()) ? levelVO.getRemark().trim() : "");
            return levelConfig;
        }).collect(Collectors.toList());

        memberLevelConfigRepository.saveAll(levelConfigs);

        return Wrapper.success();
    }

    /**
     * 修改会员等级
     *
     * @param headers  Http头部信息
     * @param updateVO 接口参数
     * @return 操作结果
     */
    @Transactional(rollbackFor = BusinessException.class)
    @Override
    public Wrapper<Void> updateMemberLevel(HttpHeaders headers, MemberLevelUpdateVO updateVO) {
        UserLoginCacheDTO loginUser = memberCacheService.checkUserFromCache(headers);

        MemberLevelConfigDO levelConfig = memberLevelConfigRepository.findById(updateVO.getLevelId()).orElse(null);
        if(levelConfig == null || !levelConfig.getMemberId().equals(loginUser.getMemberId()) || !levelConfig.getRoleId().equals(loginUser.getMemberRoleId())) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_LEVEL_CONFIG_DOES_NOT_EXISTS);
        }

        //根据等级、下级角色Id 判断等级是否已经存在
        if(memberLevelConfigRepository.existsByMemberIdAndRoleIdAndLevelAndSubRoleIdAndIdNot(loginUser.getMemberId(), loginUser.getMemberRoleId(), updateVO.getLevel(), levelConfig.getSubRoleId(), updateVO.getLevelId())) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_LEVEL_CONFIG_EXISTS);
        }

        //只修改名称等信息
        levelConfig.setLevel(updateVO.getLevel());
        levelConfig.setLevelTag(updateVO.getLevelTag());
        levelConfig.setScoreTag(updateVO.getScoreTag());
        levelConfig.setRemark(StringUtils.hasText(updateVO.getRemark()) ? updateVO.getRemark().trim() : "");

        memberLevelConfigRepository.saveAndFlush(levelConfig);

        return Wrapper.success();
    }

    /**
     * 查询会员等级详情
     *
     * @param headers Http头部信息
     * @param idVO    接口参数
     * @return 查询结果
     */
    @Transactional(rollbackFor = BusinessException.class)
    @Override
    public Wrapper<MemberLevelDetailVO> findMemberLevel(HttpHeaders headers, MemberLevelIdVO idVO) {
        UserLoginCacheDTO loginUser = memberCacheService.checkUserFromCache(headers);
        MemberLevelConfigDO levelConfig = memberLevelConfigRepository.findById(idVO.getLevelId()).orElse(null);
        if(levelConfig == null || !levelConfig.getMemberId().equals(loginUser.getMemberId()) || !levelConfig.getRoleId().equals(loginUser.getMemberRoleId())) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_LEVEL_CONFIG_DOES_NOT_EXISTS);
        }

        RoleDO role = roleRepository.findById(levelConfig.getSubRoleId()).orElse(null);
        if(role == null) {
            return Wrapper.fail(ResponseCode.MC_MS_ROLE_DOES_NOT_EXIST);
        }

        MemberLevelDetailVO detailVO = new MemberLevelDetailVO();
        detailVO.setLevelId(levelConfig.getId());
        detailVO.setLevel(levelConfig.getLevel());
        detailVO.setLevelTag(levelConfig.getLevelTag());
        detailVO.setLevelType(levelConfig.getLevelType());
        detailVO.setLevelTypeName(MemberLevelTypeEnum.getCodeMsg(levelConfig.getLevelType()));
        detailVO.setScoreTag(levelConfig.getScoreTag());
        detailVO.setStatus(levelConfig.getStatus());
        detailVO.setStatusName(EnableDisableStatus.getNameByCode(levelConfig.getStatus()));
        detailVO.setRemark(levelConfig.getRemark());
        detailVO.setRoles(Stream.of(new RoleQueryVO(role.getId(), role.getRoleName(), role.getRoleType().getTypeEnum(), role.getMemberType().getTypeEnum())).collect(Collectors.toList()));

        return Wrapper.success(detailVO);
    }

    /**
     * 修改会员等级状态
     *
     * @param headers  Http头部信息
     * @param statusVO 接口参数
     * @return 操作结果
     */
    @Transactional(rollbackFor = BusinessException.class)
    @Override
    public Wrapper<Void> updateMemberLevelStatus(HttpHeaders headers, MemberLevelStatusVO statusVO) {
        UserLoginCacheDTO loginUser = memberCacheService.checkUserFromCache(headers);
        MemberLevelConfigDO levelConfig = memberLevelConfigRepository.findById(statusVO.getLevelId()).orElse(null);
        if(levelConfig == null || !levelConfig.getMemberId().equals(loginUser.getMemberId()) || !levelConfig.getRoleId().equals(loginUser.getMemberRoleId())) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_LEVEL_CONFIG_DOES_NOT_EXISTS);
        }

        //如果已经被关联，不能停用
        if(statusVO.getStatus().equals(EnableDisableStatus.DISABLE.getCode()) && memberLevelRightRepository.existsByMemberIdAndRoleIdAndLevelConfig(loginUser.getMemberId(), loginUser.getMemberRoleId(), levelConfig)) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_LEVEL_CAN_NOT_DISABLED);
        }

        levelConfig.setStatus(statusVO.getStatus());

        memberLevelConfigRepository.saveAndFlush(levelConfig);
        return Wrapper.success();
    }

    /**
     * 删除会员等级
     *
     * @param headers Http头部信息
     * @param idVO    接口参数
     * @return 操作结果
     */
    @Transactional(rollbackFor = BusinessException.class)
    @Override
    public Wrapper<Void> deleteMemberLevel(HttpHeaders headers, MemberLevelIdVO idVO) {
        UserLoginCacheDTO loginUser = memberCacheService.checkUserFromCache(headers);
        MemberLevelConfigDO levelConfig = memberLevelConfigRepository.findById(idVO.getLevelId()).orElse(null);
        if(levelConfig == null || !levelConfig.getMemberId().equals(loginUser.getMemberId()) || !levelConfig.getRoleId().equals(loginUser.getMemberRoleId())) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_LEVEL_CONFIG_DOES_NOT_EXISTS);
        }

        //状态为有效时不能删除
        if(levelConfig.getStatus().equals(EnableDisableStatus.ENABLE.getCode())) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_LEVEL_CAN_NOT_DELETE);
        }

        memberLevelConfigRepository.delete(levelConfig);
        return Wrapper.success();
    }

    /**
     * 权益与升级阈值 - 选择会员权益
     *
     * @param headers Http头部信息
     * @return 查询结果
     */
    @Transactional(rollbackFor = BusinessException.class)
    @Override
    public Wrapper<List<BaseMemberRightQueryVO>> findMemberLevelRights(HttpHeaders headers) {
        UserLoginCacheDTO loginUser = memberCacheService.checkUserFromCache(headers);

        QBaseRightConfigDO qBaseRightConfig = QBaseRightConfigDO.baseRightConfigDO;
        JPAQuery<BaseMemberRightQueryVO> query = jpaQueryFactory.select(Projections.constructor(BaseMemberRightQueryVO.class, qBaseRightConfig.id, qBaseRightConfig.rightTypeEnum, qBaseRightConfig.acquireWayEnum, qBaseRightConfig.paramWayEnum))
                .from(qBaseRightConfig)
                .where(qBaseRightConfig.status.eq(EnableDisableStatus.ENABLE.getCode()))
                .orderBy(qBaseRightConfig.rightTypeEnum.asc());

        //平台后台没有价格权益
        if(loginUser.getLoginSource().equals(UserLoginSourceEnum.BUSINESS_MANAGEMENT_PLATFORM.getCode())) {
            query.where(qBaseRightConfig.rightTypeEnum.ne(MemberRightTypeEnum.PRICE_RIGHT.getCode()));
        }

        return Wrapper.success(query.fetch());
    }

    /**
     * 权益与升级阈值 - 查询详情
     *
     * @param headers Http头部信息
     * @param idVO    接口参数
     * @return 查询结果
     */
    @Transactional(rollbackFor = BusinessException.class)
    @Override
    public Wrapper<MemberLevelRightDetailVO> findMemberLevelRightDetail(HttpHeaders headers, MemberLevelIdVO idVO) {
        UserLoginCacheDTO loginUser = memberCacheService.checkUserFromCache(headers);
        MemberLevelConfigDO levelConfig = memberLevelConfigRepository.findById(idVO.getLevelId()).orElse(null);
        if(levelConfig == null || !levelConfig.getMemberId().equals(loginUser.getMemberId()) || !levelConfig.getRoleId().equals(loginUser.getMemberRoleId())) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_LEVEL_CONFIG_DOES_NOT_EXISTS);
        }

        RoleDO role = roleRepository.findById(levelConfig.getSubRoleId()).orElse(null);
        if(role == null) {
            return Wrapper.fail(ResponseCode.MC_MS_ROLE_DOES_NOT_EXIST);
        }

        return Wrapper.success(new MemberLevelRightDetailVO(levelConfig.getId(), levelConfig.getLevel(), levelConfig.getLevelTag(), levelConfig.getLevelType(), levelConfig.getScoreTag(), levelConfig.getRemark(), levelConfig.getSubRoleId(), role.getRoleName(), role.getRoleType().getTypeEnum(), role.getMemberType().getTypeEnum(), levelConfig.getPoint(), levelConfig.getRights().stream().map(right -> new MemberRightDetailVO(right.getId(), right.getRightType(), right.getAcquireWay(), right.getParamWay(), right.getParameter(), right.getStatus())).collect(Collectors.toList())));
    }

    /**
     * 修改升级阈值、权益列表
     *
     * @param headers Http头部信息
     * @param pointVO 接口参数
     * @return 操作结果
     */
    @Transactional(rollbackFor = BusinessException.class)
    @Override
    public Wrapper<Void> updateMemberLevelRight(HttpHeaders headers, MemberLevelRightUpdateVO pointVO) {
        UserLoginCacheDTO loginUser = memberCacheService.checkUserFromCache(headers);

        //升级阈值要大于前一个等级，小于后一个等级
        List<MemberLevelConfigDO> levelConfigs = memberLevelConfigRepository.findByMemberIdAndRoleId(loginUser.getMemberId(), loginUser.getMemberRoleId());
        MemberLevelConfigDO levelConfig = levelConfigs.stream().filter(config -> config.getId().equals(pointVO.getLevelId())).findFirst().orElse(null);
        if(levelConfig == null) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_LEVEL_CONFIG_DOES_NOT_EXISTS);
        }

        //查找前一个等级
        MemberLevelConfigDO lastLevelConfig = levelConfigs.stream().filter(config -> config.getSubRoleId().equals(levelConfig.getSubRoleId()) && config.getLevel().compareTo(levelConfig.getLevel()) < 0).max(Comparator.comparingInt(MemberLevelConfigDO::getLevel)).orElse(null);
        if(Objects.nonNull(lastLevelConfig) && lastLevelConfig.getPoint().compareTo(pointVO.getPoint()) >= 0) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_LEVEL_POINT_MUST_GREATER_THAN_LOWER_LEVEL);
        }

        //查找下一个等级
        MemberLevelConfigDO nextLevelConfig = levelConfigs.stream().filter(config -> config.getSubRoleId().equals(levelConfig.getSubRoleId()) && config.getLevel().compareTo(levelConfig.getLevel()) > 0).min(Comparator.comparingInt(MemberLevelConfigDO::getLevel)).orElse(null);
        if(Objects.nonNull(nextLevelConfig) && nextLevelConfig.getPoint().compareTo(pointVO.getPoint()) <= 0) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_LEVEL_POINT_MUST_LESS_THAN_UPPER_LEVEL);
        }

        //如果前端删除掉所有权益，则删除权益
        if(CollectionUtils.isEmpty(pointVO.getRights())) {
            memberRightConfigRepository.deleteAll(levelConfig.getRights());
            levelConfig.setRights(new HashSet<>());
            levelConfig.setPoint(pointVO.getPoint());
            memberLevelConfigRepository.saveAndFlush(levelConfig);
            return Wrapper.success();
        }

        List<BaseRightConfigDO> baseRightConfigs = baseRightConfigRepository.findByRightTypeEnumIn(pointVO.getRights().stream().map(MemberRightTypeParamVO::getRightType).collect(Collectors.toList()));
        if(baseRightConfigs.size() != pointVO.getRights().size()) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_RIGHT_DOES_NOT_EXIST);
        }

        //删除前端去掉的
        List<MemberRightConfigDO> memberRights = new ArrayList<>(levelConfig.getRights());
        memberRights.removeIf(right -> pointVO.getRights().stream().noneMatch(r -> r.getRightType().equals(right.getRightType())));

        //更改参数
        memberRights.forEach(right -> pointVO.getRights().stream().filter(r -> r.getRightType().equals(right.getRightType())).findFirst().ifPresent(r -> right.setParameter(r.getParameter().divide(BigDecimal.valueOf(100), 4, RoundingMode.HALF_UP))));

        //新增（这里要用 Collectors.toList()， 如果用 Collectors.toSet()，只会新增一条
        List<MemberRightConfigDO> newMemberRightConfigs = pointVO.getRights().stream().filter(right -> memberRights.stream().noneMatch(exist -> exist.getRightType().equals(right.getRightType()))).map(right -> {
            BaseRightConfigDO baseRightConfig = baseRightConfigs.stream().filter(b -> b.getRightTypeEnum().equals(right.getRightType())).findFirst().orElse(null);
            if(baseRightConfig == null) {
                return null;
            }

            MemberRightConfigDO rightConfig = new MemberRightConfigDO();
            rightConfig.setMemberId(loginUser.getMemberId());
            rightConfig.setRoleId(loginUser.getMemberRoleId());
            rightConfig.setRightType(baseRightConfig.getRightTypeEnum());
            rightConfig.setAcquireWay(baseRightConfig.getAcquireWayEnum());
            rightConfig.setParamWay(baseRightConfig.getParamWayEnum());
            rightConfig.setParameter(right.getParameter().divide(BigDecimal.valueOf(100), 4, RoundingMode.HALF_UP));
            rightConfig.setStatus(EnableDisableStatus.ENABLE.getCode());
            return rightConfig;
        }).filter(Objects::nonNull).collect(Collectors.toList());

        memberRights.addAll(newMemberRightConfigs);
        memberRightConfigRepository.saveAll(memberRights);

        levelConfig.setRights(new HashSet<>(memberRights));
        levelConfig.setPoint(pointVO.getPoint());
        memberLevelConfigRepository.saveAndFlush(levelConfig);

        return Wrapper.success();
    }

    /**
     * 修改权益参数
     *
     * @param headers Http头部信息
     * @param paramVO 接口参数
     * @return 操作结果
     */
    @Transactional(rollbackFor = BusinessException.class)
    @Override
    public Wrapper<Void> updateRightParameter(HttpHeaders headers, MemberRightParamVO paramVO) {
        UserLoginCacheDTO loginUser = memberCacheService.checkUserFromCache(headers);
        MemberRightConfigDO memberRightConfig = memberRightConfigRepository.findById(paramVO.getRightId()).orElse(null);
        if(memberRightConfig == null || !memberRightConfig.getMemberId().equals(loginUser.getMemberId()) || !memberRightConfig.getRoleId().equals(loginUser.getMemberRoleId())) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_RIGHT_DOES_NOT_EXIST);
        }

        memberRightConfig.setParameter(paramVO.getParameter().divide(BigDecimal.valueOf(100), 4, RoundingMode.HALF_UP));
        memberRightConfigRepository.saveAndFlush(memberRightConfig);
        return Wrapper.success();
    }

    /**
     * 修改权益状态
     *
     * @param headers  Http头部新
     * @param statusVO 接口参数
     * @return 操作结果
     */
    @Transactional(rollbackFor = BusinessException.class)
    @Override
    public Wrapper<Void> updateRightStatus(HttpHeaders headers, MemberRightStatusVO statusVO) {
        UserLoginCacheDTO loginUser = memberCacheService.checkUserFromCache(headers);
        MemberRightConfigDO memberRightConfig = memberRightConfigRepository.findById(statusVO.getRightId()).orElse(null);
        if(memberRightConfig == null || !memberRightConfig.getMemberId().equals(loginUser.getMemberId()) || !memberRightConfig.getRoleId().equals(loginUser.getMemberRoleId())) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_RIGHT_DOES_NOT_EXIST);
        }

        memberRightConfig.setStatus(statusVO.getStatus());
        memberRightConfigRepository.saveAndFlush(memberRightConfig);
        return Wrapper.success();
    }

    /**
     * 将所有没有配置会员等级的下级会员，初始化为最小会员等级
     *
     * @param headers Http头部信息
     * @return 操作结果
     */
    @Transactional(rollbackFor = BusinessException.class)
    @Override
    public Wrapper<Void> rebuildMemberLevelRight(HttpHeaders headers) {
        UserLoginCacheDTO loginUser = memberCacheService.checkUserFromCache(headers);
        //Step 1: 查询下级会员当前等级配置中，没有关联MemberLevelConfigDO的
        Specification<MemberLevelRightDO> specification = (Specification<MemberLevelRightDO>) (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();

            list.add(criteriaBuilder.equal(root.get("memberId").as(Long.class), loginUser.getMemberId()));
            list.add(criteriaBuilder.equal(root.get("roleId").as(Long.class), loginUser.getMemberId()));
            list.add(criteriaBuilder.isNotNull(root.get("relation").as(MemberRelationDO.class)));
            list.add(criteriaBuilder.isNull(root.get("levelConfig").as(MemberLevelConfigDO.class)));

            Predicate[] p = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(p));
        };

        //如果没有，表示已经全部设置了等级，返回成功
        List<MemberLevelRightDO> levelRights = memberLevelRightRepository.findAll(specification);
        if(CollectionUtils.isEmpty(levelRights)) {
            return Wrapper.success();
        }

        //Step 2: 查找当前会员所有等级配置，如果没有则返回成功
        List<MemberLevelConfigDO> levelConfigs = memberLevelConfigRepository.findByMemberIdAndRoleId(loginUser.getMemberId(), loginUser.getMemberRoleId());
        if(CollectionUtils.isEmpty(levelConfigs)) {
            return Wrapper.success();
        }

        //Step 3: 循环每一个下级会员关系进行修改
        List<MemberLevelRightDO> updateList = new ArrayList<>();
        for (MemberLevelRightDO levelRight : levelRights) {
            //根据下级会员角色查询最小等级，如果没有，不修改
            MemberLevelConfigDO firstLevelConfig = levelConfigs.stream().filter(config -> config.getSubRoleId().equals(levelRight.getSubRoleId()) && config.getStatus().equals(EnableDisableStatus.ENABLE.getCode())).min(Comparator.comparingInt(MemberLevelConfigDO::getLevel)).orElse(null);
            if(firstLevelConfig == null) {
                continue;
            }

            levelRight.setLevel(firstLevelConfig.getLevel());
            levelRight.setLevelTag(firstLevelConfig.getLevelTag());
            levelRight.setLevelConfig(firstLevelConfig);
            updateList.add(levelRight);
        }

        if(!CollectionUtils.isEmpty(updateList)) {
            memberLevelRightRepository.saveAll(updateList);
        }

        return Wrapper.success();
    }

    /**
     * 查询平台会员的等级、权益、信用积分
     * @param headers Http头部信息
     * @param levelVO 接口参数
     * @return 平台会员的等级、权益、信用积分
     */
    @Override
    public Wrapper<MemberLrcVO> getPlatformMemberLrc(HttpHeaders headers, MemberIdAndRoleIdVO levelVO) {
        MemberRelationDO relationDO = relationRepository.findFirstBySubMemberIdAndSubRoleIdAndRelType(levelVO.getMemberId(), levelVO.getRoleId(), MemberRelationTypeEnum.PLATFORM.getCode());
        if(relationDO == null) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_RELATION_DOES_NOT_EXIST);
        }

        MemberLrcVO lrcVO = new MemberLrcVO();
        lrcVO.setLevel(0);
        lrcVO.setLevelTag("");
        lrcVO.setScore(0);
        lrcVO.setSumReturnMoney(new BigDecimal(0));
        lrcVO.setSumPoint(0);
        lrcVO.setCurrentPoint(0);
        lrcVO.setSumUsedPoint(0);
        lrcVO.setCreditPoint(0);
        lrcVO.setTradeCommentPoint(0);
        lrcVO.setAfterSaleCommentPoint(0);
        lrcVO.setComplainPoint(0);
        lrcVO.setRegisterYearsPoint(0);
        lrcVO.setRegisterYears(DateTimeUtil.diffYears(relationDO.getCreateTime(), LocalDateTime.now()));

        MemberLevelRightDO levelRightDO = relationDO.getLevelRight();
        if(levelRightDO != null) {
            lrcVO.setLevel(levelRightDO.getLevel());
            lrcVO.setLevelTag(levelRightDO.getLevelTag());
            lrcVO.setScore(levelRightDO.getScore());
            lrcVO.setSumReturnMoney(levelRightDO.getSumReturnMoney());
            lrcVO.setSumPoint(levelRightDO.getSumPoint());
            lrcVO.setCurrentPoint(levelRightDO.getCurrentPoint());
            lrcVO.setSumUsedPoint(levelRightDO.getSumUsedPoint());
        }

        return Wrapper.success(lrcVO);
    }
}
